package com.jf.net.adapter

import kotlinx.coroutines.flow.Flow
import okhttp3.Response
import retrofit2.Call
import retrofit2.CallAdapter
import retrofit2.Retrofit
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

/**
 * FlowDataCallFactory
 * @author hao.yin
 * @time 2023/10/23 11:39
 * @description
 */
class FlowDataCallFactory private constructor(private val async: Boolean) : CallAdapter.Factory()  {

    companion object{

        private const val TAG = SEConst.TAG_NET
        private const val TITLE = "FlowDataCallFactory"

        @JvmStatic
        @JvmOverloads
        fun create(async: Boolean = false): FlowDataCallFactory {
            return FlowDataCallFactory(async)
        }

    }

    /**
     * 根据参数返回该接口方法的CallAdapter
     *
     * @param returnType,代表api接口方法的返回值类型
     * @param annotations 为该接口方法的注解
     * @param retrofit retrofit实例
     * @return CallAdapter<*, *>?
     * */
    override fun get(
        returnType: Type,
        annotations: Array<out Annotation>,
        retrofit: Retrofit
    ): CallAdapter<*, *>? {
        //如果返回值原始类型不是Flow类型，直接返回null，表示不做处理
        if (getRawType(returnType) != Flow::class.java) {
            return null
        }
        //强制返回值类型为Flow<R>,而不是Flow
        if (returnType !is ParameterizedType) {
            //SELog.e(TAG, TITLE, "the flow type must be parameterized as Flow<Foo>!")
            throw IllegalStateException("the flow type must be parameterized as Flow<Foo>!")
        }
        //获取Flow的泛型参数
        val flowableType = getParameterUpperBound(0, returnType as ParameterizedType)
        //获取Flow的泛型参数的原始类型
        val rawFlowableType = getRawType(flowableType)

        return if (rawFlowableType == Response::class.java) {
            //Flow<T>中的T为retrofit2.Response，但不是泛型Response<R>模式
            if (flowableType !is ParameterizedType) {
                throw IllegalStateException("the response type must be parameterized as Response<Foo>!")
            }
            //选取Response的泛型参数作为ResponseBody，创建Flow<Response<R>>模式的FlowCallAdapter
            ResponseFlowCallAdapter(getParameterUpperBound(0, flowableType), async)
        } else {
            //直接将Flow的泛型参数作为ResponseBody,创建Flow<R>模式的FlowCallAdapter
            //SELog.d(TAG, TITLE, "createResponseFlowCallAdapter by rspBodyType=$flowableType async=$async")
            BodyFlowCallAdapter(flowableType, async)
        }
    }

    /**
     * Flow<R>模式的FlowCallAdapter
     * */
    class BodyFlowCallAdapter<R> (
        private val rspBodyType: R,
        private val async: Boolean = false
    ) : BaseFlowCallAdapter<R, R>() {

        override fun responseType(): Type {
            return rspBodyType as Type
        }

        override fun adapt(call: Call<R>): Flow<R> {
            return if(async){
                asyncBodyFlow(call)
            }else{
                bodyFlow(call)
            }
        }
    }

    /**
     * Flow<Response<R>>模式的FlowCallAdapter
     * */
    class ResponseFlowCallAdapter<R> (
        private val rspBodyType: R,
        private val async: Boolean = false
    ): BaseFlowCallAdapter<R, retrofit2.Response<R>>() {

        override fun responseType(): Type {
            return  rspBodyType as Type
        }

        override fun adapt(call: Call<R>): Flow<retrofit2.Response<R>> {
            return if(async){
                asyncResponseFlow(call)
            }else {
                responseFlow(call)
            }
        }
    }
}

